import time
import json
import sys
from utils.library.request_library import RequestsLibrary
from apps.case.serializers import CaseResultSerializers
from apps.plan.models import Plan

def is_json(json_str):
    """
    verify json_str is or not json string
    """
    try:
        json_obj = json.loads(json_str)
    except ValueError:
        return False
    return True


class TestCase:
    def __init__(self, data, plan_id):
        self.data = data
        self.plan_id = plan_id
        self.name = data['name']
        self.id = data['id']
        self.is_pass = False
        self.log = []
        self.request = RequestsLibrary()
        self.steps = data['steps']
        self.return_values = {}
        self.steam = sys.stderr

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def is_has_key(self, k):
        if k in self.return_values:
            return True
        else:
            return False

    @staticmethod
    def get_params(params, params_type):
        param_dict = {}
        for param in params:
            if param['type'] == params_type:
                param_dict.update({
                    param['name']: param['value']
                })
        return param_dict

    def get_return_value_from_response(self, response, step_num, return_value):
        k = '_'.join(['step', str(step_num), return_value['type'], return_value['name']])
        try:
            for p in return_value['path'].split('.')[1:]:
                response = response[p]
            return {k: response}
        except KeyError as e:
            self.log.append(e)
            print(e)

    def collect_return_values(self, response, step_num, return_values):
        for return_value in return_values:
            r = self.get_return_value_from_response(response, step_num, return_value)
            self.return_values.update(r)

    def collect_params(self, params):
        for k, v in params.items():
            if v.startswith('$') and self.is_has_key(v.lstrip('$')):
                params[k] = self.return_values[v.lstrip('$')]

    def run(self):
        try:
            for step in self.steps:
                if step['type'] == 'interface':
                    print('======开始执行第{}个操作步骤'.format(step['step_num']))
                    method = step['step_info']['method']
                    url = step['step_info']['url']
                    params = self.get_params(step['params'], 'body')
                    self.collect_params(params)
                    headers = self.get_params(step['params'], 'headers')
                    step_num = step['step_num']
                    return_values = step['return_values']
                    response = self.request.user_request(method, url, params, headers)
                    if len(return_values):
                        self.collect_return_values(json.loads(response.json()), step_num, return_values)
            self.is_pass = True
            self.save_result()
        except Exception as e:
            self.log.append(e)
            self.save_result()

    def save_result(self):
        data = {
            'name': self.name + str(time.time()),
            'result': 1 if self.is_pass else 0,
            'plan': Plan.objects.get(id=self.plan_id)
        }
        s = CaseResultSerializers(data=data)
        if s.is_valid():
            s.save()
